package com.course.web.component.custom;

import com.course.domain.enums.TaskType;
import com.course.domain.enums.Week;
import com.course.web.biz.WebSpecBiz;
import com.course.web.component.base.BaseEdit;
import com.course.web.component.base.BaseGrid;
import com.course.web.component.base.EditGrid;
import com.course.web.model.SpecInfoVM;
import com.course.web.model.SpecWeekVM;
import com.course.web.view.SpecListView;
import com.google.common.collect.Lists;
import com.vaadin.data.Binder;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.*;
import com.vaadin.ui.themes.ValoTheme;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * Created by Justin on 2017/6/10.
 */
@SpringComponent
@ViewScope
public class SpecWeekGrid extends EditGrid<SpecWeekVM> {

    private final WebSpecBiz specBiz;

    private SpecInfoVM info;
    private Button addBtn;
    private Button pubBtn;
    private Button savBtn;
    private List<SpecWeekVM> originWeeks;

    public SpecWeekGrid(WebSpecBiz specBiz) {
        super(SpecWeekVM.class);
        this.specBiz = specBiz;
        this.originWeeks = Lists.newLinkedList();
    }

    @Override
    protected void doInitMenu(Layout menu) {
        this.addBtn = new Button("增加");
        this.savBtn = new Button("保存");
        this.pubBtn = new Button("发布");
        Button back = new Button("返回");

        menu.addComponent(addBtn);
        menu.addComponent(savBtn);
        menu.addComponent(pubBtn);
        menu.addComponent(back);

        addBtn.addClickListener(event -> createShow());
        savBtn.addClickListener(event -> save());
        pubBtn.addClickListener(event -> {
            info.lock();
            addBtn.setEnabled(false);
            pubBtn.setEnabled(false);
            savBtn.setEnabled(false);
            specBiz.updateInfo(info);
        });
        back.addClickListener(event -> getUI().getNavigator().navigateTo(SpecListView.NAME));
    }

    @Override
    protected void doInitGrid(BaseGrid<SpecWeekVM> grid) {
        grid.addColumn(SpecWeekVM::getPartIdx, "序号");
        grid.addColumn(SpecWeekVM::getWorkday, "平日时段");
        for (int i = 0; i < 7; i++) {
            int weekDay = i + 1;
            grid.addColumn(week -> week.getTask(weekDay).getTitle(), Week.of(weekDay).getTitle());
        }
        grid.addColumn(SpecWeekVM::getWeekend, "周末时段");
        grid.addButton(this::updateShow, "编辑");
        grid.addButton(this::deleteShow, "删除");
    }

    @Override
    protected void doInitEdit(BaseEdit<SpecWeekVM> edit) {
        Binder<SpecWeekVM> binder = edit.binder();
        FormLayout form = new FormLayout();
        TextField partIdx = new TextField("序号");
        TextField workday = new TextField("平日时段");
        TextField weekend = new TextField("周末时段");
        form.addComponent(partIdx);
        form.addComponent(workday);
        form.addComponent(weekend);
        form.setMargin(false);
        for (int i = 0; i < 7; i++) {
            int weekDay = i + 1;
            RadioButtonGroup<TaskType> ratio = ratio(Week.of(weekDay).getTitle());
            form.addComponent(ratio);
            binder.bind(ratio, vm -> vm.getTask(weekDay), (vm, value) -> vm.setTask(weekDay, value));
        }
        StringToIntegerConverter converter = new StringToIntegerConverter("输入数字");
        binder.forField(partIdx).asRequired("不能为空").withConverter(converter).bind("partIdx");
        binder.bind(workday, "workday");
        binder.bind(weekend, "weekend");
        edit.initEdit(form);
    }

    @Override
    public void createShow() {
        if (info.isLocked()) {
            return;
        }
        super.createShow();
    }

    @Override
    public void updateShow(SpecWeekVM item) {
        if (info.isLocked()) {
            return;
        }
        super.updateShow(item);
    }

    @Override
    public void deleteShow(SpecWeekVM item) {
        if (info.isLocked()) {
            return;
        }
        super.deleteShow(item);
    }

    @Override
    protected SpecWeekVM doCreate() {
        SpecWeekVM item = new SpecWeekVM();
        item.setSpecId(info.getId());
        item.setPartIdx(genPartIdx());
        item.setWorkday("");
        item.setWeekend("");
        TaskType[] tasks = new TaskType[8];
        for (int weekDay = 1; weekDay <= 7; weekDay++) {
            tasks[weekDay] = TaskType.NONE;
        }
        item.setTasks(tasks);
        return item;
    }

    @Override
    protected SpecWeekVM doCreate(SpecWeekVM item) {
        return item;
    }

    @Override
    protected SpecWeekVM doUpdate(SpecWeekVM item) {
        return item;
    }

    @Override
    protected SpecWeekVM doDelete(SpecWeekVM item) {
        return item;
    }

    @Override
    protected void doSort() {
        Comparator<SpecWeekVM> comparator = Comparator.comparing(SpecWeekVM::getPartIdx);
        sort(comparator);
        int index = 0;
        for (SpecWeekVM item : getItems()) {
            index = index + 1;
            item.setPartIdx(index);
        }
    }

    private void save() {
        specBiz.saveWeek(getItems(), originWeeks);
    }

    private int genPartIdx() {
        return getItems().size() + 1;
    }

    private RadioButtonGroup<TaskType> ratio(String caption) {
        List<TaskType> options = Arrays.asList(TaskType.NONE, TaskType.LEARN, TaskType.CLASS, TaskType.EVENT);
        RadioButtonGroup<TaskType> group = new RadioButtonGroup<>(caption, options);
        group.setItemCaptionGenerator(TaskType::getTitle);
        group.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);
        return group;
    }


    public void enter(int specId) {
        info = specBiz.loadInfo(specId);
        boolean enabled = !info.isLocked();
        addBtn.setEnabled(enabled);
        savBtn.setEnabled(enabled);
        pubBtn.setEnabled(enabled);
        init(specBiz.listWeek(specId));
        originWeeks.clear();
        originWeeks.addAll(getItems());
    }
}
